{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "torch_forecasting.ipynb",
      "provenance": [],
      "collapsed_sections": [
        "gNeLqMdghsjZ"
      ],
      "authorship_tag": "ABX9TyONmFmtBUAmL+bPOygdQOhB",
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/stxupengyu/LSTM-for-Time-Series-Forecasting-Pytorch/blob/main/torch_forecasting.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gNeLqMdghsjZ"
      },
      "source": [
        "#google drive"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "JsHo6Jbdv8kJ",
        "outputId": "15e6eb95-1524-422e-a45f-18b872bd356c"
      },
      "source": [
        "from google.colab import drive\r\n",
        "drive.mount('/content/drive')"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Drive already mounted at /content/drive; to attempt to forcibly remount, call drive.mount(\"/content/drive\", force_remount=True).\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "_F-Guahov-wA",
        "outputId": "e5656d0b-66ce-42c3-cc7b-29c55371314a"
      },
      "source": [
        "import os\r\n",
        "os.chdir('/content/drive/My Drive/Project/torch_gru')\r\n",
        "!ls"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "data.xls  gru_torch_3.ipynb  lstm_cnn_avg.ipynb\n",
            "gru.h5\t  gru_torch.ipynb    lstm_torch.ipynb\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZHd3VeCAhwZA"
      },
      "source": [
        "#Read data"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TiX08q3ewA42",
        "outputId": "0065ff60-56e0-4670-ab50-f183363fceba"
      },
      "source": [
        "import numpy as np\r\n",
        "import pandas as pd\r\n",
        "import matplotlib.pyplot as plt\r\n",
        "from sklearn.preprocessing import MinMaxScaler\r\n",
        "from sklearn.metrics import mean_squared_error\r\n",
        "from sklearn.metrics import mean_absolute_error\r\n",
        "import torch\r\n",
        "from torch import nn, optim\r\n",
        "from torch.autograd import Variable\r\n",
        "from torch.utils.data import DataLoader\r\n",
        "import torch.utils.data as Data\r\n",
        "from torchvision import transforms, datasets\r\n",
        "plt.style.use('ggplot')\r\n",
        "\r\n",
        "seq_length = 3#time step\r\n",
        "input_size = 3#input dim\r\n",
        "hidden_size = 6\r\n",
        "num_layers = 1\r\n",
        "num_classes = 1\r\n",
        "learning_rate = 0.0001\r\n",
        "batch_size = 64\r\n",
        "n_iters = 5000\r\n",
        "split_ratio = 0.9\r\n",
        "data_path = 'data.xls'\r\n",
        "\r\n",
        "def read_data(data_path):\r\n",
        "  '''\r\n",
        "  read original data, show and plot\r\n",
        "  '''\r\n",
        "  data = pd.read_excel(data_path)\r\n",
        "  data=data.iloc[:,:3]\r\n",
        "  label=data.iloc[:,2:]\r\n",
        "  print(data.head())\r\n",
        "  # plt.plot(data.iloc[:,0])\r\n",
        "  # plt.show()\r\n",
        "  return data,label\r\n",
        "\r\n",
        "def normalization(data,label):\r\n",
        "  '''\r\n",
        "  normalization\r\n",
        "  '''\r\n",
        "  mm_x = MinMaxScaler()\r\n",
        "  mm_y = MinMaxScaler()  \r\n",
        "  data = data.values\r\n",
        "  data = mm_x.fit_transform(data)\r\n",
        "  label = mm_y.fit_transform(label)\r\n",
        "  return data, label, mm_y\r\n",
        "\r\n",
        "def sliding_windows(data, seq_length):\r\n",
        "  '''\r\n",
        "  Output:The data form we can feed GRU\r\n",
        "  '''\r\n",
        "  x = []\r\n",
        "  y = []\r\n",
        "  for i in range(len(data)-seq_length-1):\r\n",
        "      _x = data[i:(i+seq_length),:]\r\n",
        "      _y = data[i+seq_length,-1]\r\n",
        "      x.append(_x)\r\n",
        "      y.append(_y)\r\n",
        "  x, y = np.array(x),np.array(y)\r\n",
        "  print('x.shape,y.shape:\\n',x.shape,y.shape)\r\n",
        "  return x, y\r\n",
        "\r\n",
        "def data_split(x, y, split_ratio):\r\n",
        "  '''\r\n",
        "  convert to torch format and split train&test\r\n",
        "  '''\r\n",
        "  train_size = int(len(y) * split_ratio)\r\n",
        "  test_size = len(y) - train_size\r\n",
        "\r\n",
        "  x_data = Variable(torch.Tensor(np.array(x)))\r\n",
        "  y_data = Variable(torch.Tensor(np.array(y)))\r\n",
        "\r\n",
        "  x_train = Variable(torch.Tensor(np.array(x[0:train_size])))\r\n",
        "  y_train = Variable(torch.Tensor(np.array(y[0:train_size])))\r\n",
        "  x_test = Variable(torch.Tensor(np.array(x[train_size:len(x)])))\r\n",
        "  y_test = Variable(torch.Tensor(np.array(y[train_size:len(y)])))\r\n",
        "\r\n",
        "  print('x_train.shape,y_train.shape,x_test.shape,y_test.shape:\\n',x_train.shape,y_train.shape,x_test.shape,y_test.shape)  \r\n",
        "  return x_data, y_data, x_train, y_train, x_test, y_test\r\n",
        "\r\n",
        "def data_generator(x_train, y_train, x_test, y_test, n_iters, batch_size):\r\n",
        "  '''\r\n",
        "  generate DataLoader\r\n",
        "  '''\r\n",
        "  num_epochs = n_iters / (len(x_train) / batch_size)\r\n",
        "  num_epochs = int(num_epochs)\r\n",
        "  train_dataset = Data.TensorDataset(x_train, y_train)\r\n",
        "  test_dataset = Data.TensorDataset(x_test, y_test)\r\n",
        "  train_loader = torch.utils.data.DataLoader(dataset=train_dataset, \r\n",
        "                                            batch_size=batch_size, \r\n",
        "                                            shuffle=False)\r\n",
        "  test_loader = torch.utils.data.DataLoader(dataset=test_dataset, \r\n",
        "                                            batch_size=batch_size, \r\n",
        "                                            shuffle=False)\r\n",
        "  return train_loader, test_loader, num_epochs\r\n",
        "\r\n",
        "data,label = read_data(data_path) \r\n",
        "data, label, mm_y = normalization(data, label)\r\n",
        "x, y = sliding_windows(data, seq_length)\r\n",
        "x_data, y_data, x_train, y_train, x_test, y_test = data_split(x, y, split_ratio)\r\n",
        "train_loader, test_loader, num_epochs = data_generator(x_train, y_train, x_test, y_test, n_iters, batch_size)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "   导叶开度  燃料流量m3N/h  压气机出口温度\n",
            "0     1     0.0089      1.0\n",
            "1     2     0.0179      2.0\n",
            "2     3     0.0269      2.0\n",
            "3     6     0.0359      3.0\n",
            "4     8     0.0449      4.0\n",
            "x.shape,y.shape:\n",
            " (604, 3, 3) (604,)\n",
            "x_train.shape,y_train.shape,x_test.shape,y_test.shape:\n",
            " torch.Size([543, 3, 3]) torch.Size([543]) torch.Size([61, 3, 3]) torch.Size([61])\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Jzzb-jIlcFWH"
      },
      "source": [
        "#Model"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "EtLIFOD1rymF",
        "outputId": "70fa47cd-1300-4a7a-e49e-3daee5f3a11c"
      },
      "source": [
        "import torch.nn as nn\r\n",
        "import torch.nn.functional as F\r\n",
        "\r\n",
        "class BP(nn.Module):\r\n",
        "    def __init__(self, num_classes, input_size, hidden_size, num_layers):\r\n",
        "        super(BP, self).__init__()\r\n",
        "        self.num_classes = num_classes\r\n",
        "        self.num_layers = num_layers\r\n",
        "        self.input_size = input_size\r\n",
        "        self.hidden_size = hidden_size\r\n",
        "        self.seq_length = seq_length\r\n",
        "        self.fc1 = nn.Linear(seq_length*input_size, 20)\r\n",
        "        self.fc2 = nn.Linear(20, 20)\r\n",
        "        self.fc3 = nn.Linear(20, num_classes)\r\n",
        "        self.dropout = nn.Dropout(0.2)\r\n",
        "\r\n",
        "    def forward(self, x):      \r\n",
        "        out = x.view(-1, self.seq_length*self.input_size)     \r\n",
        "        out = F.relu(self.fc1(out))\r\n",
        "        out = F.relu(self.fc2(out))#F.relu()\r\n",
        "        out = self.fc3(out)\r\n",
        "        return out\r\n",
        "\r\n",
        "class GRU(nn.Module):\r\n",
        "    def __init__(self, num_classes, input_size, hidden_size, num_layers):\r\n",
        "        super(GRU, self).__init__()\r\n",
        "        \r\n",
        "        self.num_classes = num_classes\r\n",
        "        self.num_layers = num_layers\r\n",
        "        self.input_size = input_size\r\n",
        "        self.hidden_size = hidden_size\r\n",
        "        self.seq_length = seq_length\r\n",
        "        \r\n",
        "        self.gru = nn.GRU(input_size=input_size, hidden_size=hidden_size,\r\n",
        "                            num_layers=num_layers, batch_first=True)\r\n",
        "        \r\n",
        "        self.fc1 = nn.Linear(hidden_size, 20)\r\n",
        "        self.fc2 = nn.Linear(20, num_classes)\r\n",
        "        self.dropout = nn.Dropout(0.2)\r\n",
        "\r\n",
        "    def forward(self, x):\r\n",
        "        h_0 = Variable(torch.zeros(\r\n",
        "            self.num_layers, x.size(0), self.hidden_size))    \r\n",
        "        # Propagate input through GRU\r\n",
        "        ula, h_out  = self.gru(x, h_0)\r\n",
        "        h_out = h_out.view(-1, self.hidden_size)\r\n",
        "        out = F.relu(self.fc1(h_out))\r\n",
        "        out = self.fc2(out)\r\n",
        "        return out\r\n",
        "\r\n",
        "class LSTM(nn.Module):\r\n",
        "    def __init__(self, num_classes, input_size, hidden_size, num_layers):\r\n",
        "        super(LSTM, self).__init__()\r\n",
        "        \r\n",
        "        self.num_classes = num_classes\r\n",
        "        self.num_layers = num_layers\r\n",
        "        self.input_size = input_size\r\n",
        "        self.hidden_size = hidden_size\r\n",
        "        self.seq_length = seq_length\r\n",
        "        \r\n",
        "        self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size,\r\n",
        "                            num_layers=num_layers, batch_first=True)\r\n",
        "        \r\n",
        "        self.fc = nn.Linear(hidden_size, num_classes)\r\n",
        "\r\n",
        "    def forward(self, x):\r\n",
        "        h_0 = Variable(torch.zeros(\r\n",
        "            self.num_layers, x.size(0), self.hidden_size))\r\n",
        "        \r\n",
        "        c_0 = Variable(torch.zeros(\r\n",
        "            self.num_layers, x.size(0), self.hidden_size))\r\n",
        "        \r\n",
        "        # Propagate input through LSTM\r\n",
        "        ula, (h_out, _) = self.lstm(x, (h_0, c_0))\r\n",
        "        \r\n",
        "        h_out = h_out.view(-1, self.hidden_size)\r\n",
        "        \r\n",
        "        out = self.fc(h_out)\r\n",
        "        \r\n",
        "        return out\r\n",
        "\r\n",
        "mymodel = GRU(num_classes, input_size, hidden_size, num_layers)\r\n",
        "print(mymodel)\r\n",
        "criterion = torch.nn.MSELoss()    # mean-squared error for regression\r\n",
        "optimizer = torch.optim.Adam(mymodel.parameters(), lr=learning_rate)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "GRU(\n",
            "  (gru): GRU(3, 6, batch_first=True)\n",
            "  (fc1): Linear(in_features=6, out_features=20, bias=True)\n",
            "  (fc2): Linear(in_features=20, out_features=1, bias=True)\n",
            "  (dropout): Dropout(p=0.2, inplace=False)\n",
            ")\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ZVYwDFCNcjF_"
      },
      "source": [
        "#Train"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gbLk_ibAqGcl",
        "outputId": "b183ca6e-7275-4a23-d9aa-7fa863316889"
      },
      "source": [
        "# Training \r\n",
        "iter=0 \r\n",
        "for epochs in range(num_epochs):\r\n",
        "  for i,(batch_x, batch_y) in enumerate (train_loader): \r\n",
        "    outputs = mymodel(batch_x)\r\n",
        "    # clear the gradients\r\n",
        "    optimizer.zero_grad()   \r\n",
        "    #loss \r\n",
        "    #print(outputs.shape, batch_y.shape)\r\n",
        "    loss = criterion(outputs,batch_y)\r\n",
        "    #backpropagation \r\n",
        "    loss.backward()\r\n",
        "    optimizer.step()\r\n",
        "    iter+=1\r\n",
        "    if iter % 100 == 0:\r\n",
        "      print(\"iter: %d, loss: %1.5f\" % (iter, loss.item()))\r\n"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/torch/nn/modules/loss.py:446: UserWarning: Using a target size (torch.Size([64])) that is different to the input size (torch.Size([64, 1])). This will likely lead to incorrect results due to broadcasting. Please ensure they have the same size.\n",
            "  return F.mse_loss(input, target, reduction=self.reduction)\n",
            "/usr/local/lib/python3.6/dist-packages/torch/nn/modules/loss.py:446: UserWarning: Using a target size (torch.Size([31])) that is different to the input size (torch.Size([31, 1])). This will likely lead to incorrect results due to broadcasting. Please ensure they have the same size.\n",
            "  return F.mse_loss(input, target, reduction=self.reduction)\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "iter: 100, loss: 0.10608\n",
            "iter: 200, loss: 0.09284\n",
            "iter: 300, loss: 0.06052\n",
            "iter: 400, loss: 0.03423\n",
            "iter: 500, loss: 0.07159\n",
            "iter: 600, loss: 0.11240\n",
            "iter: 700, loss: 0.09758\n",
            "iter: 800, loss: 0.12785\n",
            "iter: 900, loss: 0.33978\n",
            "iter: 1000, loss: 0.02314\n",
            "iter: 1100, loss: 0.02443\n",
            "iter: 1200, loss: 0.03547\n",
            "iter: 1300, loss: 0.04117\n",
            "iter: 1400, loss: 0.00918\n",
            "iter: 1500, loss: 0.00558\n",
            "iter: 1600, loss: 0.01549\n",
            "iter: 1700, loss: 0.04192\n",
            "iter: 1800, loss: 0.18253\n",
            "iter: 1900, loss: 0.02118\n",
            "iter: 2000, loss: 0.01910\n",
            "iter: 2100, loss: 0.02834\n",
            "iter: 2200, loss: 0.03339\n",
            "iter: 2300, loss: 0.00790\n",
            "iter: 2400, loss: 0.00500\n",
            "iter: 2500, loss: 0.01217\n",
            "iter: 2600, loss: 0.01992\n",
            "iter: 2700, loss: 0.08916\n",
            "iter: 2800, loss: 0.01007\n",
            "iter: 2900, loss: 0.00780\n",
            "iter: 3000, loss: 0.01581\n",
            "iter: 3100, loss: 0.02103\n",
            "iter: 3200, loss: 0.00580\n",
            "iter: 3300, loss: 0.00492\n",
            "iter: 3400, loss: 0.00907\n",
            "iter: 3500, loss: 0.01127\n",
            "iter: 3600, loss: 0.03063\n",
            "iter: 3700, loss: 0.00367\n",
            "iter: 3800, loss: 0.00119\n",
            "iter: 3900, loss: 0.00652\n",
            "iter: 4000, loss: 0.01164\n",
            "iter: 4100, loss: 0.00473\n",
            "iter: 4200, loss: 0.00466\n",
            "iter: 4300, loss: 0.00642\n",
            "iter: 4400, loss: 0.01421\n",
            "iter: 4500, loss: 0.01654\n",
            "iter: 4600, loss: 0.00344\n",
            "iter: 4700, loss: 0.00036\n",
            "iter: 4800, loss: 0.00332\n",
            "iter: 4900, loss: 0.00815\n",
            "iter: 5000, loss: 0.00463\n",
            "iter: 5100, loss: 0.00410\n",
            "iter: 5200, loss: 0.00469\n",
            "iter: 5300, loss: 0.01509\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 614
        },
        "id": "EDe9H0DuwFQh",
        "outputId": "2ab10727-dba3-4ace-f0f1-b08cb3bda208"
      },
      "source": [
        "def result(x_data, y_data):\r\n",
        "  mymodel.eval()\r\n",
        "  train_predict = mymodel(x_data)\r\n",
        "\r\n",
        "  data_predict = train_predict.data.numpy()\r\n",
        "  y_data_plot = y_data.data.numpy()\r\n",
        "  y_data_plot = np.reshape(y_data_plot, (-1,1))  \r\n",
        "  data_predict = mm_y.inverse_transform(data_predict)\r\n",
        "  y_data_plot = mm_y.inverse_transform(y_data_plot)\r\n",
        "\r\n",
        "  plt.plot(y_data_plot)\r\n",
        "  plt.plot(data_predict)\r\n",
        "  plt.legend(('real', 'predict'),fontsize='15')\r\n",
        "  plt.show()\r\n",
        "\r\n",
        "  print('MAE/RMSE')\r\n",
        "  print(mean_absolute_error(y_data_plot, data_predict))\r\n",
        "  print(np.sqrt(mean_squared_error(y_data_plot, data_predict) ))\r\n",
        "\r\n",
        "result(x_data, y_data)\r\n",
        "result(x_test,y_test)"
      ],
      "execution_count": null,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "MAE/RMSE\n",
            "33.589046\n",
            "38.83998\n"
          ],
          "name": "stdout"
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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ee+99/qieV0o3EVEeuimm27i17/+Nddee2239/nlL3+pcBcR6U3hcLhXj5efn8/o0aPJzs7u1eP2BoW7iGSkOXPmcPfdd/Pee+8xadIkKisrue+++9i3b19qm/Lycn72s58xb948brrpJurq6oDOG3YsXLiQ2tpahg4dSl1d3RfuxhSNRnn22We54YYbGDFiBPPnz+9yv1U4/7BMIpFg1apVTJgwgaFDhzJ69GjmzJkDwNSpU6mvr+ff/u3fKC8vp7y8nLfeeqtPfj5az11EMtaxY8f4yU9+wpNPPonL5WL58uVMmzaNDz/8EJfLBcDq1asZO3YsK1euJJlMAvDwww+zc+dOfvSjHzFkyBA2bNjAQw89xLvvvpu6Rd/ixYt58803eeqpp6ipqeGNN97gnXfeuWSbnn76ad5++20effRRxo0bR2trK++++27qmD/4wQ8YPHhwKvCrqqr64kejcBeRTmu2nuBQayQt33tokYv/WzvwS+/n9/t5+eWXGTNmDAAjR45k/Pjx/Ou//it/8zd/A0BJSQmrV69O7fO73/2O3/72t7z99tuMGzcOgMmTJ/PJJ5+wcuVKfv7zn+P3+3n99df50Y9+xCOPPALA7bffzu23337R9hw4cIA333yT5557ju9///up5++9914AampqyMnJobi4mNGjRwN9tza9hmVEJGN5vd5UsANUVFQwcuRIdu7cmXruzjvv7LLPhx9+SElJCWPGjCEej6e+JkyYQH19PQB79uwhEonwta99LbWf1Wrt8vh8fv/73wPwwAMPXHZtl0s9dxEB6FHPOd28Xu8XnisuLqa5uTn1eMCAAV1e9/v9NDc3n3eGi81mA+DkyZOpY33+2BfT2tpKTk4O+fn53SugDyncRSRjne/2hz6fj5qamtRji8XS5fXCwkJKS0t5+eWXL3jcs78QfD4fRUVFXY59MUVFRYRCIdra2tIe8BqWEZGM1dLSwpYtW1KPGxoa2LVrF6NGjbrgPhMmTODkyZPk5uZy8803f+EL4Prrr8flcrFx48bUfslkssvj87ntttsAePvtty+4TVZWFtFotFv1XQ713EUkY3k8HmbPns1TTz2Vmi3j9XovOuY9adIkJk+ezLe//W1mzpxJTU0N7e3t7N69m2g0yjPPPIPH4+HBBx9k+fLl2Gw2rrvuOt544w2CweBF2zNs2DAefPBB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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "stream",
          "text": [
            "MAE/RMSE\n",
            "67.69218\n",
            "68.09824\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "uAJxtOzzxqLN"
      },
      "source": [
        ""
      ],
      "execution_count": null,
      "outputs": []
    }
  ]
}